package com.gaojinqi.base.common.enums;

import com.google.common.collect.Lists;

import java.util.List;
import java.util.Optional;

/**
 * 获取枚举的工具类
 *
 * @author gaojinqi
 * @version 1.0
 * @since 2020年04月09日
 */
public class EnumHelper {

    /**
     * 根据code获取枚举
     *
     * @param enumClass   继承 {@link IEnum IEnum} 接口的枚举类
     * @param code        code
     * @param defaultEnum 默认的枚举常量
     * @param <E>         code所对应的枚举常量
     * @param <T>         code类型
     * @return code所对应的枚举常量或者默认的枚举常量
     * @see IEnum
     */
    public static <E extends IEnum<T>, T> E findByCode(Class<E> enumClass, T code, E defaultEnum) {
        for (E enumConstant : enumClass.getEnumConstants()) {
            if (enumConstant.getCode().equals(code)) {
                return enumConstant;
            }
        }
        return defaultEnum;
    }

    /**
     * 根据name获取枚举
     *
     * @param enumClass   继承 {@link IEnum IEnum} 接口的枚举类
     * @param name        code
     * @param defaultEnum 默认的枚举常量
     * @param <E>         name所对应的枚举常量
     * @return code所对应的枚举常量或者默认的枚举常量
     * @see IEnum
     */
    public static <E extends IEnum<T>, T> E findByName(Class<E> enumClass, String name, E defaultEnum) {
        for (E enumConstant : enumClass.getEnumConstants()) {
            if (enumConstant.getName().equals(name)) {
                return enumConstant;
            }
        }
        return defaultEnum;
    }

    /**
     * 强制根据code获取枚举，获取不到则会抛指定异常
     *
     * @param enumClass 继承 {@link IEnum  IEnum} 接口的枚举类
     * @param code      code
     * @param exception 抛出指定runtimeException异常
     * @param <E>       code所对应的枚举常量
     * @param <T>       code类型
     * @return code所对应的枚举常量或者默认的枚举常量
     * @see IEnum
     */
    public static <E extends IEnum<T>, T> E findByCodeUrgently(Class<E> enumClass, T code, RuntimeException exception) {
        return
                Optional.ofNullable(
                        findByCode(enumClass, code, null)
                ).orElseThrow(
                        () -> exception
                );
    }


    /**
     * 强制根据name获取枚举，获取不到则会抛指定异常
     *
     * @param enumClass 继承 {@link IEnum IEnum} 接口的枚举类
     * @param name      code
     * @param exception 抛出指定runtimeException异常
     * @param <E>       name所对应的枚举常量
     * @return code所对应的枚举常量或者默认的枚举常量
     * @see IEnum
     */
    public static <E extends IEnum<T>, T> E findByNameUrgently(Class<E> enumClass, String name, RuntimeException exception) {
        return
                Optional.ofNullable(
                        findByName(enumClass, name, null)
                ).orElseThrow(
                        () -> exception
                );
    }

    /**
     * 获取所有枚举
     *
     * @param enumClass 继承 {@link IEnum IEnum} 接口的枚举类
     * @return 所有枚举
     */
    public static <E extends IEnum<T>, T> List<E> getAllEnum(Class<E> enumClass) {
        return Lists.newArrayList(enumClass.getEnumConstants());
    }

    /**
     * 获取所有code
     */
    public static <E extends IEnum<T>, T> List<T> getAllCode(Class<E> enumClass) {
        List<T> codeList = Lists.newArrayList();
        for (E enumConstant : enumClass.getEnumConstants()) {
            codeList.add(enumConstant.getCode());
        }
        return codeList;
    }

    /**
     * 获取所有name
     */
    public static <E extends IEnum<T>, T> List<String> getAllName(Class<E> enumClass) {
        List<String> nameList = Lists.newArrayList();
        for (E enumConstant : enumClass.getEnumConstants()) {
            nameList.add(enumConstant.getName());
        }
        return nameList;
    }

}